package com.cskaoyan.javase.oop2._0encapsulate;

import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext;

/**
 * 封装的简单理解:
 * 封装（encapsulate）是指将数据及相关操作绑定在一起的一种编程机制，使其构成一个不可分割的独立实体。
 *
 * 在Java中，类就是这样一种结构。
 * 当然，数据被保护在类的内部，是为了尽可能地隐藏内部的细节，只保留一些对外"接口"使之与外部发生联系。
 * 注: 这里的接口不是指Java语法中的接口,而是广义上的接口,生活中的接口
 *
 * 之所以要封装，是为了将代码的使用者和实现者分开。使用者能够完全得到自己想要的功能，又不需要思考过多细节；实现者可以隐藏功能实现的细节，方便灵活进行修改而不影响使用者使用。
 *
 * 广义的封装实现,从实际的语法角度上来说
 * Java当中的封装是依赖于访问权限修饰符来实现：
 * 比如一些对外没有访问需求的成员变量,应该私有化它
 *
 * 但这种情况下,外界就真的无法直接访问
 * 为了给外界提供访问的可能性,在定义类时,可以提供Getter/Setter方法
 *
 * Getter/Setter方法的格式比较固定：
 * Getter方法提供外界访问的途径，一般命名为getXxx（Xxx是成员变量名），一般直接返回成员变量得值即可。
 * Setter方法提供外界赋值的途径，一般命名为setXxx（Xxx是成员变量名），一般使用this关键字完成赋值就可以了。
 *
 * Getter/Setter方法的优点:
 *      将成员变量的访问和赋值分开了,从之前的不可控,变为了可控
 *
 * 注意:
 *      实际开发中,如果没有特别的需求,绝大多数情况下,类中的成员变量应该私有化
 *      如果你不确定某个成员变量对外究竟是否要访问,那么无脑私有化它,一般不是一个错误的选择.
 *      但是如果一个类中的成员变量,确实有在类的外部频繁访问的需求,也可以根据情况选择访问权限.
 *
 *      在绝大多数情况下,私有化成员变量,然后根据需求提供Getter/Setter方法,是常规的做法
 *
 * @since 16:20
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student();
        // s.score;
        System.out.println(s.getScore());
        s.setScore(100);
        System.out.println(s.getScore());
        System.out.println("---------------");
        Student s2 = new Student(25);
        System.out.println(s2.getAge());

        s2.setAge(1000);
        s2.setAge(20);
        System.out.println(s2.getAge());


    }
}

class Student {
    private double score;
    private int age;

    public Student() {
    }

    public Student(int age) {
        this.age = age;
    }

    // age的Getter方法
    public int getAge() {
        return age;
    }

    // age的Setter方法
    public void setAge(int age) {
        if (age <= 0) {
            System.out.println("你活回去了吗?");
            return;
        }
        if (age > 141){
            System.out.println("你这个年龄,是修真大成了吗!");
            return;
        }
        this.age = age;
        System.out.println("成功赋值!");
    }

    // score的Getter方法
    public double getScore() {
        return score;
    }

    // score的Setter方法
    public void setScore(double score) {
        this.score = score;
    }
}
